package com.achao.twoway.twowaydragrecyclerview;

import android.content.Context;
import android.graphics.Point;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/**
 * description：
 * author：liuchao
 * time：2018/12/6 16:40
 */
public class DragRecyclerViewLayout extends FrameLayout {
    /**
     * 1:如何生成拖拽块（截图功能）
     * 2：判断拖拽块进入item
     * 3：拖拽块在屏幕边缘的检测
     */

    private static final String TAG = "DragRecyclerViewLayout";

    private ViewDragHelper mViewDragHelper;
    private TextView mDragView;
    private RecyclerView mRvList;
    private Point dragViewPoint;
    private Point dragViewStartPoint;
    private List<OnItemViewDragListener> mOnDragListeners;
    private int dragStartPosition = -1;
    // 当前拖拽块滑动是否是释放后的滑动
    private boolean isReleasingBack = false;

    public void setOnDragListeners(List<OnItemViewDragListener> onDragListeners) {
        mOnDragListeners = onDragListeners;
    }

    public void addDragListener(OnItemViewDragListener onDragListener) {
        if (mOnDragListeners == null) {
            mOnDragListeners = new ArrayList<>();
        }
        mOnDragListeners.add(onDragListener);
    }

    public void clearAllDragListener() {
        if (mOnDragListeners != null) {
            mOnDragListeners.clear();
        }
    }

    public void removeOnDragListener(OnItemViewDragListener onDragListener) {
        if (mOnDragListeners != null) {
            mOnDragListeners.remove(onDragListener);
        }
    }


    public DragRecyclerViewLayout(@NonNull Context context) {
        this(context, null);
    }

    public DragRecyclerViewLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public DragRecyclerViewLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
      /*  int action = ev.getAction();
        if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
            mViewDragHelper.cancel();
            return false;
        }
        return mViewDragHelper.shouldInterceptTouchEvent(ev);*/
        //由viewDragHelper 来判断是否应该拦截此事件
        startDrag(ev);
        boolean result = mViewDragHelper.shouldInterceptTouchEvent(ev);
        Log.i(TAG, "onInterceptTouchEvent: result-->"+result);
        return result;
    }


    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        // 当前控件拦截触摸事件
        mViewDragHelper.processTouchEvent(ev);
        return true;
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if (mViewDragHelper.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(this);
        }
    }

    private int dragViewWidth = 0;
    private int dragViewHeigt = 0;

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mDragView = findViewById(R.id.drag_view);
        mRvList = findViewById(R.id.rv_list);
        dragViewWidth = mDragView.getWidth();
        dragViewHeigt = mDragView.getHeight();
    }

    private void init() {
        dragViewStartPoint = new Point();
        mViewDragHelper = ViewDragHelper.create(this, 0.5f, new ViewDragHelper.Callback() {

            // 此方法用于判断是否捕获当前child的触摸事件，可以指定ViewDragHelper移动哪一个子View
            @Override
            public boolean tryCaptureView(@NonNull View child, int pointerId) {
                return child == mDragView;
            }

            // 此方法在View被开始捕获和解析时回调，即当tryCaptureView()中的返回值为true的时候，此方法才会被调用
            @Override
            public void onViewCaptured(@NonNull View capturedChild, int activePointerId) {
                super.onViewCaptured(capturedChild, activePointerId);
                int dragViewStartX = mDragView.getLeft();
                int dragViewStartY = mDragView.getTop();
                dragViewStartPoint.x = dragViewStartX;
                dragViewStartPoint.x = dragViewStartY;
                int position = getDragViewPositionWithRvItem();
                dragStartPosition = position;
                if (mOnDragListeners != null && !isReleasingBack) {
                    for (OnItemViewDragListener itemViewDragListener : mOnDragListeners) {
                        itemViewDragListener.onStartDrag(position);
                    }
                }
            }


            @Override
            public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
                if (top < 0) { //限制上边界
                    top = 0;
                } else if (top > (getMeasuredHeight() - child.getMeasuredHeight())) {
                    //限制下边界
                    top = getMeasuredHeight() - child.getMeasuredHeight();
                }
                return top;
            }


            /**  控制child在水平方向的移动 返回多少就 多移动多少
             * @param child
             * @param left  ViewDragHelper会将当前child的left值改变成返回的值
             * @param dx    相较于上一次child在水平方向上移动的
             * @return
             */
            @Override
            public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
                // left : left = child.getLeft() + dx 若想要它不移动，则：return left - dx;
                if (left < 0) { //限制左边界
                    left = 0;
                } else if (left > (getMeasuredWidth() - child.getMeasuredWidth())) {
                    //限制右边界
                    left = getMeasuredWidth() - child.getMeasuredWidth();
                }
                return left;
            }

            /**
             * 限制移动边界
             * @param child
             * @return
             */
            @Override
            public int getViewHorizontalDragRange(@NonNull View child) {
                return getMeasuredWidth() - child.getMeasuredWidth();
            }

            @Override
            public int getViewVerticalDragRange(@NonNull View child) {
                return getMeasuredHeight() - child.getMeasuredHeight();
            }

            /**当child位置改变时执行
             * @param changedView   位置改变的子View
             * @param left           child最新的left位置
             * @param top            child最新的top位置
             * @param dx            相较于上一次水平移动的距离
             * @param dy            相较于上一次垂直移动的距离
             */
            @Override
            public void onViewPositionChanged(@NonNull View changedView, int left, int top, int dx, int dy) {
                super.onViewPositionChanged(changedView, left, top, dx, dy);
                Log.i(TAG, "onViewPositionChanged: " + " left->" + left + " top->" + top + " dx->" + dx + " dy->" + dy);
                Log.i(TAG, "onViewPositionChanged: position-> " + getDragViewPositionWithRvItem());
                mDragView.setText(getDragViewPositionWithRvItem() + "");
                if (mOnDragListeners != null && !isReleasingBack) {
                    // 当前进入的位置
                    int currentPosition = getDragViewPositionWithRvItem();
                    for (int i = 0; i < mRvList.getChildCount(); i++) {
                        View itemView = mRvList.getChildAt(i);
                        if (itemView != null) {
                            for (OnItemViewDragListener itemViewDragListener : mOnDragListeners) {
                                GridLayoutManager gridLayoutManager = (GridLayoutManager) mRvList.getLayoutManager();
                                 /*int firstVisiblePostion = gridLayoutManager.findFirstVisibleItemPosition();
                                 int lastVisiblePosition = gridLayoutManager.findLastVisibleItemPosition();*/
                                if (mRvList.getChildAdapterPosition(itemView) == currentPosition) {
                                    itemViewDragListener.onEnterView(currentPosition);
                                } else {
                                    itemViewDragListener.onExitView(currentPosition);
                                }
                                //itemViewDragListener.onViewMoving(currentPosition);
                            }
                        }
                    }
                }
            }

            @Override
            public void onViewDragStateChanged(int state) {
                super.onViewDragStateChanged(state);
                Log.i(TAG, "onViewDragStateChanged: state->" + state);
               /* if (state == ViewDragHelper.STATE_IDLE) {
                    if (mOnDragListeners != null) {
                        int position = getDragViewPositionWithRvItem();
                        for (OnItemViewDragListener itemViewDragListener : mOnDragListeners) {
                            itemViewDragListener.onEndDrag(position);
                        }
                    }
                }*/
                if (state == ViewDragHelper.STATE_IDLE) {
                    isReleasingBack = false;
                }
            }

            /**手指抬起的时候执行该方法
             * @param releasedChild   当前抬起的View
             * @param xvel             x方向移动的速度：正值：向右移动  负值：向左移动
             * @param yvel             y方向移动的速度：正值：向下移动  负值：向上移动
             */
            @Override
            public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
                super.onViewReleased(releasedChild, xvel, yvel);
                int currentPosition = getDragViewPositionWithRvItem();
                dragStartPosition = currentPosition;
                isReleasingBack = true;
                Log.i(TAG, "onViewReleased: " + " xvel->" + xvel + " yvel->" + yvel);
                if (mOnDragListeners != null) {
                    for (int i = 0; i < mRvList.getChildCount(); i++) {
                        View itemView = mRvList.getChildAt(i);
                        if (itemView != null) {
                            for (OnItemViewDragListener itemViewDragListener : mOnDragListeners) {
                                GridLayoutManager gridLayoutManager = (GridLayoutManager) mRvList.getLayoutManager();
                                /*int firstVisiblePostion = gridLayoutManager.findFirstVisibleItemPosition();
                                 int lastVisiblePosition = gridLayoutManager.findLastVisibleItemPosition();*/
                                if (mRvList.getChildAdapterPosition(itemView) == currentPosition) {
                                    boolean isPutIn = itemViewDragListener.onReleaseDrag(currentPosition);
                                    itemViewDragListener.onEndDrag(dragStartPosition, currentPosition, isPutIn);
                                    if (!isPutIn) {
                                        // 回到原来的位置
                                        mViewDragHelper.settleCapturedViewAt(dragViewStartPoint.x, dragViewStartPoint.y);
                                        invalidate();
                                    }
                                }
                            }
                        }
                    }
                }
                resetDragStatusData();
            }

            @Override
            public void onEdgeDragStarted(int edgeFlags, int pointerId) {
                super.onEdgeDragStarted(edgeFlags, pointerId);
                Log.i(TAG, "onEdgeDragStarted: pointerId->" + pointerId + " edgeFlags->" + edgeFlags);
            }

            @Override
            public void onEdgeTouched(int edgeFlags, int pointerId) {
                super.onEdgeTouched(edgeFlags, pointerId);
                Log.i(TAG, "onEdgeTouched: pointerId->" + pointerId + " edgeFlags->" + edgeFlags);
            }

            @Override
            public int getOrderedChildIndex(int index) {
                return super.getOrderedChildIndex(index);
            }
        });
        //mViewDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_ALL);
    }

    /**
     * 获取拖拽块的拖拽点：这里使用中心点
     */
    private Point getDragViewPoint() {
        if (dragViewPoint == null) {
            dragViewPoint = new Point();
        }
        int dragViewWidth = mDragView.getWidth();
        int dragViewHeight = mDragView.getHeight();
        dragViewPoint.set(mDragView.getLeft() + dragViewWidth / 2, mDragView.getTop() + dragViewHeight / 2);
        return dragViewPoint;
    }

    /**
     * 获取dragview所在recyclerview位置
     *
     * @return
     */
    private int getDragViewPositionWithRvItem() {
        Point dragViewPostion = getDragViewPoint();
        View childView = mRvList.findChildViewUnder(dragViewPostion.x, dragViewPostion.y);
        int position = mRvList.getChildAdapterPosition(childView);
        return position;
    }

    private void resetDragStatusData() {
        dragStartPosition = -1;
    }

    private void startDrag(MotionEvent ev) {
        /**
         * 获取点击处位置的item
         */
        View childView = mRvList.findChildViewUnder(ev.getX(), ev.getY());
        if (childView == null) {
            return;
        }
        int itemLeft = childView.getLeft();
        int itemTop = childView.getTop();
        int centerX = itemLeft + childView.getWidth() / 2;
        int centerY = itemTop + childView.getHeight() / 2;
        // 将拖拽块显示到指定位置
        FrameLayout.LayoutParams frameLayout = (LayoutParams) mDragView.getLayoutParams();
        frameLayout.leftMargin = centerX - mDragView.getWidth() / 2;
        frameLayout.topMargin = centerY - mDragView.getHeight() / 2;
        mDragView.setLayoutParams(frameLayout);
    }

}
